from flask import Flask, request, jsonify
from py2neo import Graph, Node, Relationship

app = Flask(__name__)

# 配置 Neo4j 数据库连接
NEO4J_URI = "bolt://localhost:7687"  # 修改为你的 Neo4j 地址
NEO4J_USERNAME = "neo4j"             # 修改为你的 Neo4j 用户名
NEO4J_PASSWORD = "714716liu"          # 修改为你的 Neo4j 密码
graph = Graph(NEO4J_URI, auth=(NEO4J_USERNAME, NEO4J_PASSWORD))


# 显示整个知识图谱
@app.route("/graph", methods=["GET"])
def get_graph():
    query = """
    MATCH (n)-[r]->(m)
    RETURN n, r, m
    """
    results = graph.run(query).data()
    graph_data = []

    for record in results:
        node_1 = {"id": record["n"].identity, "labels": list(record["n"].labels), "properties": dict(record["n"])}
        node_2 = {"id": record["m"].identity, "labels": list(record["m"].labels), "properties": dict(record["m"])}
        relationship = {"type": record["r"].__class__.__name__, "properties": dict(record["r"])}
        graph_data.append({"node_1": node_1, "relationship": relationship, "node_2": node_2})

    return jsonify(graph_data)


# 增加节点
@app.route("/add_node", methods=["POST"])
def add_node():
    data = request.json
    label = data.get("label")  # 节点类型
    properties = data.get("properties", {})  # 节点属性
    if not label:
        return jsonify({"error": "label is required"}), 400

    node = Node(label, **properties)
    graph.create(node)
    return jsonify({"message": "Node created successfully", "node": dict(node)})


# 增加关系
@app.route("/add_relationship", methods=["POST"])
def add_relationship():
    data = request.json
    start_node_id = data.get("start_node_id")  # 起始节点 ID
    end_node_id = data.get("end_node_id")  # 结束节点 ID
    rel_type = data.get("type")  # 关系类型
    properties = data.get("properties", {})  # 关系属性

    if not start_node_id or not end_node_id or not rel_type:
        return jsonify({"error": "start_node_id, end_node_id, and type are required"}), 400

    # 根据 ID 查询节点
    start_node = graph.nodes.match().where(f"ID(_) = {start_node_id}").first()
    end_node = graph.nodes.match().where(f"ID(_) = {end_node_id}").first()

    if not start_node or not end_node:
        return jsonify({"error": "Start node or end node not found"}), 404

    relationship = Relationship(start_node, rel_type, end_node, **properties)
    graph.create(relationship)
    return jsonify({"message": "Relationship created successfully"})


# 删除节点（包括相关关系）
@app.route("/delete_node/<int:node_id>", methods=["DELETE"])
def delete_node(node_id):
    node = graph.nodes.match().where(f"ID(_) = {node_id}").first()
    if not node:
        return jsonify({"error": "Node not found"}), 404

    graph.delete(node)
    return jsonify({"message": "Node and its relationships deleted successfully"})


# 删除关系
@app.route("/delete_relationship", methods=["DELETE"])
def delete_relationship():
    data = request.json
    start_node_id = data.get("start_node_id")
    end_node_id = data.get("end_node_id")
    rel_type = data.get("type")

    if not start_node_id or not end_node_id or not rel_type:
        return jsonify({"error": "start_node_id, end_node_id, and type are required"}), 400

    query = f"""
    MATCH (n)-[r:{rel_type}]->(m)
    WHERE ID(n) = {start_node_id} AND ID(m) = {end_node_id}
    DELETE r
    """
    graph.run(query)
    return jsonify({"message": "Relationship deleted successfully"})


# 查询节点
@app.route("/query_node", methods=["GET"])
def query_node():
    label = request.args.get("label")
    key = request.args.get("key")
    value = request.args.get("value")

    if not label:
        return jsonify({"error": "label is required"}), 400

    query = f"MATCH (n:{label}) WHERE n.{key} = '{value}' RETURN n" if key and value else f"MATCH (n:{label}) RETURN n"
    results = graph.run(query).data()

    nodes = [{"id": record["n"].identity, "labels": list(record["n"].labels), "properties": dict(record["n"])} for record in results]
    return jsonify(nodes)


if __name__ == "__main__":
    app.run(debug=True)